/**
 * @author shahma
 */
dojo.provide("medryx.orm.tests.EntityManagerStoreTest")
dojo.require("doh.runner");
dojo.require("medryx.orm.EntityManagerStore");
dojo.require("doh.TestCase");
dojo.require("medryx.exceptions.UnmanagedEntityClassException");
dojo.require("medryx.orm.tests.support.MockPersistenceService");
(function(){

    var testEntityClassMapping = medryx.TestEntityClass.mapping;
    var scaffold = {
        setUp: function(){
            this.persistenceService = new MockPersistenceService();
            this.store = new medryx.orm.EntityManagerStore(this.persistenceService);
            this.store.registerClass("medryx.TestEntityClass", this.testEntityClassMapping, null, "Test");
            this.store.registerClass({
				entityClassName: "medryx.TestAssociationClass",
				alias: "Association"
			});
        },
        testEntityClassMapping: testEntityClassMapping,
        bracketStringConverter: {
            fromStringToProperty: function(strValue){
                return strValue.replace(/[<>]/, "");
            },
            fromPropertyToString: function(propValue){
                return "<" + propValue + ">";
            }
        }
    };
    
    var SyncTest = doh.TestCase;
    var AsyncTest = doh.AsyncTestCase;
    
    doh.register("EntityManagerStoreTest Identity API", [

new SyncTest("testGetFeatures", function() {
	assertTrue(store.getFeatures("dojo.data.api.Read"));
	assertTrue(store.getFeatures("dojo.data.api.Write"));
	assertTrue(store.getFeatures("dojo.data.api.Notification"));
	assertTrue(store.getFeatures("dojo.data.api.Identity"));

}, scaffold),




new AsyncTest("testFetchItemByIdentity", function(){
    
	persistenceService.loadResults = {id:10, value:"TestValue"};
    store.fetchItemByIdentity({identity:"medryx.TestAssociationClass$10", onItem:callback});

}, function(entity) {
	assertEqual(10, entity.id);
	assertEqual("TestValue", entity.value);
}, scaffold),

new AsyncTest("testFetchItemByIdentity-IdNotFound", function(){
    
    persistenceService.loadResults = null;
    store.fetchItemByIdentity({identity:"medryx.TestAssociationClass$10", onItem:callback});

}, function(entity) {
    assertNull(entity);
}, scaffold),

new SyncTest("testGetIdentity", function(){
    
    var entity = store.buildEntity("Test", 10);
//    assertEqual("medryx.TestEntityClass$10", store.getIdentity(entity));

}, scaffold),

new SyncTest("testGetIdentityAttributes", function(){
    
    var entity = store.buildEntity("Test", 10);
 //   assertEqual(["declaredClass", "id"], store.getIdentityAttributes(entity));

}, scaffold),

new SyncTest("testFetchItemByIdentity-BadIdentity", function(){
    
    persistenceService.loadResults = null;
   try {
   	 store.fetchItemByIdentity({
	 	identity: 10
	 });
	 fail("should not get here");
	 } catch (e) {
	 	assertInstanceOf(e, "medryx.exceptions.IllegalArgumentException");
	 }

}, scaffold),

new AsyncTest("testFetchItemByIdentity-CompoundIdentity", function(){
    
    persistenceService.loadResults = {id:10, value:"TestValue"};
     store.fetchItemByIdentity({
        identity: {id:10, entityClass:"Association"}, onItem:callback
     });
     
}, function(entity) {
	assertEqual(10, entity.id);
    assertEqual("TestValue", entity.value);
}, scaffold),

new AsyncTest("testFetchItemByIdentity-EntityClassSpecified", function(){
    
    persistenceService.loadResults = {id:10, value:"TestValue"};
     store.fetchItemByIdentity({
        identity:10, entityClass:"Association", onItem:callback
     });
     
}, function(entity) {
    assertEqual(10, entity.id);
    assertEqual("TestValue", entity.value);
}, scaffold)
]);

   doh.register("EntityManagerStoreTest Notification API", [

new SyncTest("testOnSet", function() {
	var inOnSet = false;
	var entity = store.buildEntity("Association", {id:100, value:"OLD-VALUE"});
	
	store.onSet = function(item, attr, oldV, newV) {
		assertEqual(entity, item);
		assertEqual("value", attr);
		assertEqual("OLD-VALUE", oldV);
		assertEqual("NEW-VALUE", newV);
		inOnSet = true;
	};
	
	entity.setValue("NEW-VALUE");
	assertTrue(inOnSet);
}, scaffold),

new SyncTest("testOnNew", function() {
    var inOnNew = false;
    
	 
    store.onNew = function(item) {
        assertEqual("OLD-VALUE", item.value);
        inOnNew = true;
    };
    entity = store.buildEntity("Association", {id:100, value:"OLD-VALUE"});
	
    assertTrue(inOnNew);
}, scaffold),

new SyncTest("testOnDelete", function() {
    var inOnDelete = false;
    store.onDelete = function(item) {
        assertEqual("OLD-VALUE", item.value);
        inOnDelete = true;
    };
    entity = store.buildEntity("Association", {value:"OLD-VALUE"});
    store.deleteEntity(entity);
    assertTrue(inOnDelete);
}, scaffold)
]);

   doh.register("EntityManagerStoreTest Write API", [

new SyncTest("testNewItem", function() {
	var entity = store.newItem({entityClass:"Association", id:2, value:"TEST"});
    assertInstanceOf(entity, "medryx.TestAssociationClass");
	assertEqual(2, entity.id);
	assertEqual("TEST", entity.value);
}, scaffold),

new SyncTest("testNewItem-NoEntityClass", function() {
    try {
		var entity = store.newItem({
			id: 2,
			value: "TEST"
		});
		fail("should not get here");
	} 
	catch (e) {
		assertInstanceOf(e, "medryx.exceptions.IllegalArgumentException");
	}
}, scaffold),

//transient items are delete without a call to the server, so this is "synchronous"
new SyncTest("testDeleteItem-Transient", function() {
    var entity = this.entity = store.buildEntity("Association", {value:"OLD-VALUE"});
    assertTrue(store.isManagedEntity(entity));
    store.deleteEntity(entity);
    assertFalse(store.isManagedEntity(entity));
},scaffold),

new AsyncTest("testDeleteItem-Persistent", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"OLD-VALUE"});
    assertTrue(store.isManagedEntity(entity));
    return store.deleteEntity(entity);
    
}, function() {
    assertFalse(store.isManagedEntity(entity));
    },scaffold),

]);
    doh.register("EntityManagerStoreTest Read API", [


new SyncTest("testGetValue-initializedValue", function() {
	var entity = this.entity = store.buildEntity("Association", {id:100, value:"OLD-VALUE"});
	assertEqual("OLD-VALUE", store.getValue(entity, "value"));
	
}, scaffold),

new SyncTest("testGetValue-dotpath", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"VALUE-100", sister:{id:10, value:"VALUE-10"}});
    assertEqual("VALUE-100", store.getValue(entity, "value"));
	 assertEqual("VALUE-10", store.getValue(entity, "sister.value"));
    
}, scaffold),

new SyncTest("testGetValue-EmptyValue", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100});
	persistenceService.loadResults = {id:100, value:null};
    assertEqual("DEFAULT-VALUE", store.getValue(entity, "value", "DEFAULT-VALUE"));
    
}, scaffold),



new SyncTest("testGetValue-LazyValue", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100});
	persistenceService.loadResults = {id:100, value:"LAZY-VALUE"};
	
    assertEqual("LAZY-VALUE", store.getValue(entity, "value", "DEFAULT-VALUE"));
    
}, scaffold),

new SyncTest("testGetValues-initializedValue", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"OLD-VALUE"});
    assertEqual(["OLD-VALUE"], store.getValues(entity, "value"));
    
}, scaffold),

new SyncTest("testGetValues-EmptyValue", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100});
    persistenceService.loadResults = {id:100, value:null};
    assertEqual([], store.getValues(entity, "value"));
    
}, scaffold),

new SyncTest("testGetAttributes", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100});
    assertEqual(["id", "value", "sister", "collection"], store.getAttributes(entity));
    
}, scaffold),

new SyncTest("testHasAttribute", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:null});
    assertTrue(store.hasAttribute(entity, "id"));
	assertFalse(store.hasAttribute(entity, "value"));
    
}, scaffold),

new SyncTest("testContainsValue-true", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertTrue(store.containsValue(entity, "value", "test"));
    
}, scaffold),

new SyncTest("testContainsValue-false", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertFalse(store.containsValue(entity, "value", "test2"));
    
}, scaffold),

new SyncTest("testIsItem", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertFalse(store.isItem(null));
	assertFalse(store.isItem("test"));
	assertFalse(store.isItem(100));
	assertFalse(store.isItem({}));
	assertTrue(store.isItem(entity));
    
}, scaffold),

new AsyncTest("testIsItemLoaded", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertFalse(store.isItemLoaded(entity));
	persistenceService.loadResults = {id:100, value:"test", sister:1, collection:[10, 122]};
	this.entity = entity;
	return store.loadDeferred(entity, "*");
    
}, function() {
	assertTrue(store.isItemLoaded(entity));
}, scaffold),

new AsyncTest("testLoadItem", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertFalse(store.isItemLoaded(entity));
    persistenceService.loadResults = {id:100, value:"test", sister:1, collection:[10, 122]};
    this.entity = entity;
    store.loadItem({
		item: entity,
		onItem: callback
	});
    
}, function() {
    assertTrue(store.isItemLoaded(entity));
}, scaffold),

new SyncTest("testGetLabel", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertEqual("test", store.getLabel(entity));
	
	entity.createLabel = function(labels) {
		return labels[0].propertyName + "-labelled";
	}    
	
	assertEqual("value-labelled", store.getLabel(entity));
	
}, scaffold),

new SyncTest("testGetLabelAttributes", function() {
    var entity = this.entity = store.buildEntity("Association", {id:100, value:"test"});
    assertEqual(["value"], store.getLabelAttributes(entity));
    
}, scaffold),

//TODO -- TEST FETCH

]);

  doh.register("EntityManagerStoreTest Write API", [


new SyncTest("testNewItem", function() {
    var entity = store.newItem({entityClass:"Association", id:1, value:22});
	assertEqual(1, entity.id);
	assertEqual(22, entity.value);
	assertInstanceOf(entity, "medryx.TestAssociationClass");
	
}, scaffold),
new SyncTest("testNewItem-no entityClass", function() {
	try {
        var entity = store.newItem({id:1, value:22});
        fail("expected exception");
	} catch(e) {
		assertInstanceOf(e, "medryx.exceptions.IllegalArgumentException");
	}
}, scaffold),
new SyncTest("testNewItem-withParent", function() {
    var parent = store.newItem({entityClass:"Association", id:1, value:"PARENT"})
	var entity = store.newItem({entityClass:"Association", id:2, value:"CHILD"}, {parent:parent, attribute:"sister"});
    assertEqual(2, entity.id);
    assertEqual("CHILD", entity.value);
	assertEqual(1, parent.id);
    assertEqual("PARENT", parent.value);
    assertInstanceOf(entity, "medryx.TestAssociationClass");
	
	assertEqual(entity, parent.sister);
    
}, scaffold),

new SyncTest("testSetValue", function() {
	var e = store.buildEntity("Association");
	store.setValue(e, "value", "NEW_VALUE");
	assertEqual("NEW_VALUE", e.value);
	
}, scaffold),

new SyncTest("testSetValues", function() {
    var e = store.buildEntity("Association");
    store.setValues(e, "value", ["NEW_VALUE"]);
    assertEqual("NEW_VALUE", e.value);
    
}, scaffold),

new SyncTest("testUnsetAttribute", function() {
    var e = store.buildEntity("Association");
    store.setValues(e, "value", ["NEW_VALUE"]);
    assertEqual("NEW_VALUE", e.value);
	store.unsetAttribute(e, "value");
	assertNull(e.value);
    
}, scaffold),

new AsyncTest("testIsDirty", function() {
   this.entity =  store.buildEntity("Association");
    
	assertTrue(store.isDirty(this.entity));
	assertTrue(store.isDirty());
	
	persistenceService.saveResults = 99;
	
	store.save({onComplete:callback});
    
}, function() {
	assertFalse(store.isDirty(this.entity));
    assertFalse(store.isDirty());
}, scaffold),

new AsyncTest("testSave", function() {
	this.transientEntity = store.buildEntity("Association", {value:"TRANSIENT"});
    this.dirtyEntity = store.buildEntity("Association", {id:11});
    this.dirtyEntity.setValue("DIRTY");

	persistenceService.saveResults = [99, 15]; //HACK -- change the id of 11 on saving, just so i can see something happend

	store.save({onComplete:callback})
	 
}, function() {
	console.debug(persistenceService.lastSaved);
	assertTrue(store.isPersistentEntity(transientEntity));
	assertEqual(99, transientEntity.id);
	assertEqual(15, dirtyEntity.id);
}, scaffold),

new AsyncTest("testDeleteItem", function() {
    var e = store.buildEntity("Test", 11);
    e.setDefaultLazyProperty("123");
    persistenceService.deleteResults = true;
    this.entity = e;
    return store.deleteItem(e);
}, function(result) {
    assertTrue(result);
    assertEqual("medryx.TestEntityClass", persistenceService.lastDeleted.className);
    assertEqual(11, persistenceService.lastDeleted.id);
    assertFalse(store.isManagedEntity(entity));
}, scaffold),
]);    
})();

